package offer

import (
	// "bp/cache"
	sqlc "bp/db/sqlc"
	"bp/internal/service/param"
	// "bp/internal/service/com/offer"
)

type applyQuotaCutCouponNatureVoucherToTrialItemsParam struct {
	memberCouponPtr *sqlc.MemberCoupon
	couponPtr       *sqlc.Coupon
	itemIDsOfCoupon []param.ItemID
	itemPtrs        []*ToTrialItem
	memberID        int64
	brandID         int64
	outTransNo      string
	trialScene      string
	trialIssuer     string
}

// applyQuotaCutCouponNatureVoucherToTrialItems 将满减券应用到试算品上
func (s *OfferComServiceImp) applyQuotaCutCouponNatureVoucherToTrialItems(ptr *applyQuotaCutCouponNatureVoucherToTrialItemsParam) (
	off int32,
	upsertOffTrialParamPtr *sqlc.UpsertOffTrialParams,
	createOffTrialItemParamPtrs []*sqlc.UpsertOffTrialItemParams,
	unMatchedItemPtrs []*ToTrialItem,
	err error) {
	var amount int32
	memberCouponPtr := ptr.memberCouponPtr
	couponPtr := ptr.couponPtr
	for _, itemPtr := range ptr.itemPtrs {
		var isMatch bool
		// if couponPtr.Scope == string(sqlc.EmScopeIncludeItems) {
		// 	isMatch = s.ItemIDContains(ptr.itemIDsOfCoupon, param.ItemID(itemPtr.ItemID))
		// } else {
		// 	isMatch = !s.ItemIDContains(ptr.itemIDsOfCoupon, param.ItemID(itemPtr.ItemID))
		// }
		switch sqlc.EmScope(couponPtr.Scope) {
		case sqlc.EmScopeIncludeItems:
			isMatch = s.ItemIDContains(ptr.itemIDsOfCoupon, param.ItemID(itemPtr.ItemID))
		case sqlc.EmScopeExcludeItems:
			isMatch = !s.ItemIDContains(ptr.itemIDsOfCoupon, param.ItemID(itemPtr.ItemID))
		case sqlc.EmScopeUnlimited:
			isMatch = true
		}
		s.slog.Infof("applyQuotaCutCouponNatureVoucherToTrialItems isMatch:%d(%s), %v", memberCouponPtr.CouponID, memberCouponPtr.Sn, isMatch)
		if isMatch {
			amount += itemPtr.ItemPrice * itemPtr.DetailCnt
			createOffTrialItemParamPtrs = append(createOffTrialItemParamPtrs, &sqlc.UpsertOffTrialItemParams{
				OutTransNo:     ptr.outTransNo,
				TrialScene:     ptr.trialScene,
				SceneDetailID:  itemPtr.DetailID,
				SceneDetailCnt: itemPtr.DetailCnt,
				ItemID:         itemPtr.ItemID,
				ItemSpecID:     itemPtr.ItemSpecID,
				ItemPrice:      itemPtr.ItemPrice,
				Cnt:            itemPtr.DetailCnt,
				Off:            0, // 多品促销按各个品加起来计算
			})
		} else {
			unMatchedItemPtrs = append(unMatchedItemPtrs, itemPtr)
		}
	}
	if amount > 0 {
		off = s.memberCouponOff(amount, memberCouponPtr)
		offerItemTrialInfoBytes, marshalErr := s.MarshalOfferItemTrialInfoOfMemberCoupon(memberCouponPtr)
		if marshalErr != nil {
			err = marshalErr
			return
		}
		upsertOffTrialParamPtr = &sqlc.UpsertOffTrialParams{
			MemberID:           ptr.memberID,
			OutTransNo:         ptr.outTransNo,
			TrialScene:         ptr.trialScene,
			TrialIssuer:        ptr.trialIssuer,
			BrandID:            ptr.brandID,
			OwnerType:          memberCouponPtr.OwnerType,
			OwnerID:            memberCouponPtr.OwnerID,
			Off:                off,
			OfferType:          memberCouponPtr.OfferType,
			OfferItemType:      string(sqlc.EmOfferItemTypeCoupon),
			OfferItemID:        memberCouponPtr.CouponID,
			OfferItemTrialInfo: offerItemTrialInfoBytes,
		}
	}
	return
}

type applyPromotionToTrialItemsParam struct {
	promotionNatureItemOffPtr *sqlc.Promotion
	itemIDsOfPromotion        []param.ItemID
	itemPtrs                  []*ToTrialItem
	memberID                  int64
	brandID                   int64
	outTransNo                string
	trialScene                string
	trialIssuer               string
}

// ApplyNatureItemOffPromotionToTrialItems 将单品促销活动应用到试算品上
func (s *OfferComServiceImp) applyNatureItemOffPromotionToTrialItems(ptr *applyPromotionToTrialItemsParam) (
	off int32,
	upsertOffTrialParamPtr *sqlc.UpsertOffTrialParams,
	createOffTrialItemParamPtrs []*sqlc.UpsertOffTrialItemParams,
	unMatchedItemPtrs []*ToTrialItem,
	err error) {
	promotionPtr := ptr.promotionNatureItemOffPtr
	for _, itemPtr := range ptr.itemPtrs {
		var isMatch bool
		// if promotionPtr.Scope == string(sqlc.EmScopeIncludeItems) {
		// 	isMatch = s.ItemIDContains(ptr.itemIDsOfPromotion, param.ItemID(itemPtr.ItemID))
		// } else {
		// 	isMatch = !s.ItemIDContains(ptr.itemIDsOfPromotion, param.ItemID(itemPtr.ItemID))
		// }
		switch sqlc.EmScope(promotionPtr.Scope) {
		case sqlc.EmScopeIncludeItems:
			isMatch = s.ItemIDContains(ptr.itemIDsOfPromotion, param.ItemID(itemPtr.ItemID))
		case sqlc.EmScopeExcludeItems:
			isMatch = !s.ItemIDContains(ptr.itemIDsOfPromotion, param.ItemID(itemPtr.ItemID))
		case sqlc.EmScopeUnlimited:
			isMatch = true
		}
		if isMatch {
			amount := itemPtr.ItemPrice * itemPtr.DetailCnt
			offOfTrialItem := s.promotionOff(amount, promotionPtr)
			createOffTrialItemParamPtrs = append(createOffTrialItemParamPtrs, &sqlc.UpsertOffTrialItemParams{
				OutTransNo:     ptr.outTransNo,
				TrialScene:     ptr.trialScene,
				SceneDetailID:  itemPtr.DetailID,
				SceneDetailCnt: itemPtr.DetailCnt,
				ItemID:         itemPtr.ItemID,
				ItemSpecID:     itemPtr.ItemSpecID,
				ItemPrice:      itemPtr.ItemPrice,
				Cnt:            itemPtr.DetailCnt,
				Off:            offOfTrialItem,
			})
			off += offOfTrialItem
		} else {
			unMatchedItemPtrs = append(unMatchedItemPtrs, itemPtr)
		}
	}

	if len(createOffTrialItemParamPtrs) > 0 {
		offerItemTrialInfoBytes, marshalErr := s.MarshalOfferItemTrialInfoOfPromotion(promotionPtr)
		if marshalErr != nil {
			err = marshalErr
			return
		}
		upsertOffTrialParamPtr = &sqlc.UpsertOffTrialParams{
			MemberID:           ptr.memberID,
			OutTransNo:         ptr.outTransNo,
			TrialScene:         ptr.trialScene,
			TrialIssuer:        ptr.trialIssuer,
			BrandID:            ptr.brandID,
			OwnerType:          promotionPtr.OwnerType,
			OwnerID:            promotionPtr.OwnerID,
			Off:                off,
			OfferType:          promotionPtr.OfferType,
			OfferItemType:      string(sqlc.EmOfferItemTypeActivity),
			OfferItemID:        promotionPtr.ID,
			OfferItemTrialInfo: offerItemTrialInfoBytes,
		}
	}
	return
}

// applyNatureItemOffsPromotionToTrialItems 将多品促销活动应用到试算品上
func (s *OfferComServiceImp) applyNatureItemsOffPromotionToTrialItems(ptr *applyPromotionToTrialItemsParam) (
	off int32,
	upsertOffTrialParamPtr *sqlc.UpsertOffTrialParams,
	createOffTrialItemParamPtrs []*sqlc.UpsertOffTrialItemParams,
	unMatchedItemPtrs []*ToTrialItem,
	err error) {
	var amount int32
	promotionPtr := ptr.promotionNatureItemOffPtr
	for _, itemPtr := range ptr.itemPtrs {
		var isMatch bool
		switch sqlc.EmScope(promotionPtr.Scope) {
		case sqlc.EmScopeIncludeItems:
			isMatch = s.ItemIDContains(ptr.itemIDsOfPromotion, param.ItemID(itemPtr.ItemID))
		case sqlc.EmScopeExcludeItems:
			isMatch = !s.ItemIDContains(ptr.itemIDsOfPromotion, param.ItemID(itemPtr.ItemID))
		case sqlc.EmScopeUnlimited:
			isMatch = true
		}
		if isMatch {
			amount += itemPtr.ItemPrice * itemPtr.DetailCnt
			createOffTrialItemParamPtrs = append(createOffTrialItemParamPtrs, &sqlc.UpsertOffTrialItemParams{
				OutTransNo:     ptr.outTransNo,
				TrialScene:     ptr.trialScene,
				SceneDetailID:  itemPtr.DetailID,
				SceneDetailCnt: itemPtr.DetailCnt,
				ItemID:         itemPtr.ItemID,
				ItemSpecID:     itemPtr.ItemSpecID,
				ItemPrice:      itemPtr.ItemPrice,
				Cnt:            itemPtr.DetailCnt,
				Off:            0, // 多品促销按各个品加起来计算
			})
		} else {
			unMatchedItemPtrs = append(unMatchedItemPtrs, itemPtr)
		}
	}
	if amount > 0 {
		off = s.promotionOff(amount, promotionPtr)
		offerItemTrialInfoBytes, marshalErr := s.MarshalOfferItemTrialInfoOfPromotion(promotionPtr)
		if marshalErr != nil {
			err = marshalErr
			return
		}
		upsertOffTrialParamPtr = &sqlc.UpsertOffTrialParams{
			MemberID:           ptr.memberID,
			OutTransNo:         ptr.outTransNo,
			TrialScene:         ptr.trialScene,
			TrialIssuer:        ptr.trialIssuer,
			BrandID:            ptr.brandID,
			OwnerType:          promotionPtr.OwnerType,
			OwnerID:            promotionPtr.OwnerID,
			Off:                off,
			OfferType:          promotionPtr.OfferType,
			OfferItemType:      string(sqlc.EmOfferItemTypeActivity),
			OfferItemID:        promotionPtr.ID,
			OfferItemTrialInfo: offerItemTrialInfoBytes,
		}
	}
	return
}

type applyCardDiscountToRemainAmountParam struct {
	cardDiscountPtr *sqlc.CardDiscount
	amount          int32
	memberID        int64
	brandID         int64
	outTransNo      string
	trialScene      string
	trialIssuer     string
}

func (s *OfferComServiceImp) applyCardDiscountToRemainAmount(ptr *applyCardDiscountToRemainAmountParam) (
	off int32,
	upsertOffTrialParamPtr *sqlc.UpsertOffTrialParams,
	err error) {
	cardDiscountPtr := ptr.cardDiscountPtr
	off = s.cardDiscountOff(ptr.amount, cardDiscountPtr)
	offerItemTrialInfoBytes, marshalErr := s.MarshalOfferItemTrialInfoOfCardDiscount(cardDiscountPtr, ptr.memberID)
	if marshalErr != nil {
		err = marshalErr
		return
	}
	upsertOffTrialParamPtr = &sqlc.UpsertOffTrialParams{
		MemberID:           ptr.memberID,
		OutTransNo:         ptr.outTransNo,
		TrialScene:         ptr.trialScene,
		TrialIssuer:        ptr.trialIssuer,
		BrandID:            ptr.brandID,
		OwnerType:          cardDiscountPtr.OwnerType,
		OwnerID:            cardDiscountPtr.OwnerID,
		Off:                off,
		OfferType:          cardDiscountPtr.OfferType,
		OfferItemType:      string(sqlc.EmOfferItemTypeCard),
		OfferItemID:        cardDiscountPtr.OutCardID,
		OfferItemTrialInfo: offerItemTrialInfoBytes,
	}
	return
}

type applyCardDiscountToTrialItemsParam struct {
	cardDiscountPtr       *sqlc.CardDiscount
	itemIDsOfCardDiscount []param.ItemID
	itemPtrs              []*ToTrialItem
	memberID              int64
	brandID               int64
	outTransNo            string
	trialScene            string
	trialIssuer           string
}

// applyCardDiscountToTrialItems 将卡折扣应用到试算品上
func (s *OfferComServiceImp) applyCardDiscountToTrialItems(ptr *applyCardDiscountToTrialItemsParam) (
	off int32,
	upsertOffTrialParamPtr *sqlc.UpsertOffTrialParams,
	createOffTrialItemParamPtrs []*sqlc.UpsertOffTrialItemParams,
	unMatchedItemPtrs []*ToTrialItem,
	err error) {
	cardDiscountPtr := ptr.cardDiscountPtr
	for _, itemPtr := range ptr.itemPtrs {
		var isMatch bool
		// if cardDiscountPtr.Scope == string(sqlc.EmScopeIncludeItems) {
		// 	isMatch = s.ItemIDContains(ptr.itemIDsOfCardDiscount, param.ItemID(itemPtr.ItemID))
		// } else {
		// 	isMatch = !s.ItemIDContains(ptr.itemIDsOfCardDiscount, param.ItemID(itemPtr.ItemID))
		// }
		switch sqlc.EmScope(cardDiscountPtr.Scope) {
		case sqlc.EmScopeIncludeItems:
			isMatch = s.ItemIDContains(ptr.itemIDsOfCardDiscount, param.ItemID(itemPtr.ItemID))
		case sqlc.EmScopeExcludeItems:
			isMatch = !s.ItemIDContains(ptr.itemIDsOfCardDiscount, param.ItemID(itemPtr.ItemID))
		case sqlc.EmScopeUnlimited:
			isMatch = true
		}
		s.slog.Infof("applyCardDiscountToTrialItems===amount:%+v", isMatch)
		if isMatch {
			amount := itemPtr.ItemPrice * itemPtr.DetailCnt
			offOfTrialItem := s.cardDiscountOff(amount, cardDiscountPtr)
			createOffTrialItemParamPtrs = append(createOffTrialItemParamPtrs, &sqlc.UpsertOffTrialItemParams{
				OutTransNo:     ptr.outTransNo,
				TrialScene:     ptr.trialScene,
				SceneDetailID:  itemPtr.DetailID,
				SceneDetailCnt: itemPtr.DetailCnt,
				ItemID:         itemPtr.ItemID,
				ItemSpecID:     itemPtr.ItemSpecID,
				ItemPrice:      itemPtr.ItemPrice,
				Cnt:            itemPtr.DetailCnt,
				Off:            offOfTrialItem,
			})
			off += offOfTrialItem
		} else {
			unMatchedItemPtrs = append(unMatchedItemPtrs, itemPtr)
		}
	}

	if len(createOffTrialItemParamPtrs) > 0 {
		offerItemTrialInfoBytes, marshalErr := s.MarshalOfferItemTrialInfoOfCardDiscount(cardDiscountPtr, ptr.memberID)
		if marshalErr != nil {
			err = marshalErr
			return
		}
		upsertOffTrialParamPtr = &sqlc.UpsertOffTrialParams{
			MemberID:           ptr.memberID,
			OutTransNo:         ptr.outTransNo,
			TrialScene:         ptr.trialScene,
			TrialIssuer:        ptr.trialIssuer,
			BrandID:            ptr.brandID,
			OwnerType:          cardDiscountPtr.OwnerType,
			OwnerID:            cardDiscountPtr.OwnerID,
			Off:                off,
			OfferType:          cardDiscountPtr.OfferType,
			OfferItemType:      string(sqlc.EmOfferItemTypeActivity),
			OfferItemID:        cardDiscountPtr.OutCardID,
			OfferItemTrialInfo: offerItemTrialInfoBytes,
		}
	}
	return
}
